home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 October / CD CHIP.ISO / WebServ / server7 / FiltDemo.dpr < prev    next >
Encoding:
Text File  |  1996-10-06  |  12.6 KB  |  304 lines

  1. (***************************************************************************
  2.  
  3.  
  4.  
  5.  Name:
  6.  
  7.    Delphi unit HttpFilt.dpr
  8.  
  9.  
  10.  
  11.  Notes:
  12.  
  13.    This module was built to demonstrate building an ISAPI filter with
  14.  
  15.    Delphi 2.0. This filter demonstrates all the basic functionality and
  16.  
  17.    data structures available to ISAPI filters. If compiled, it will create
  18.  
  19.    httpfilt.dll. You can add this filter to your registry, restart IIS and
  20.  
  21.    load a page from your IIS server. A log file will be written to
  22.  
  23.    c:\filtlog.svg showing each event and the filter will modify the data
  24.  
  25.    written to the HTTP user agent. This filter's purpose in life is to
  26.  
  27.    demonstrate ISAPI filters--it is very simple, but this should get you
  28.  
  29.    started with ISAPI filter writing. Best wishes,
  30.  
  31.  
  32.  
  33.    Stephen Genusa <steveg@onramp.net> 06/08/96
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  Abstract:
  40.  
  41.  
  42.  
  43.    This module contains the types, constants, and functions needed to
  44.  
  45.    create ISAPI Filter DLLs with Delphi 2.0.
  46.  
  47.  
  48.  
  49.    For more information on ISAPI, The Microsoft Internet Information FAQ is
  50.  
  51.    located at http://rampages.onramp.net/~steveg/iis.html
  52.  
  53.  
  54.  
  55.    EyeSAPI, the ISAPI extension debugger/log utility is located at
  56.  
  57.    http://rampages.onramp.net/~steveg/testisap.zip
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  Changes, fixes, and modifications; in reverse chronological order:
  64.  
  65.  
  66.  
  67.   By    Date       Description
  68.  
  69.   ----- ---------- -----------------------------------------------------------
  70.   MWT   7/6/95     Hacked up SVG's work to check filter operation
  71.  
  72.   SVG   06/08/96   Stephen Genusa <steveg@onramp.net>
  73.  
  74.                    Fixed various structures. Tested most functionality
  75.  
  76.                    and provided example code to handle each data structure.
  77.  
  78.  
  79.  
  80.   JRT   05/05/96   Jonathan R. Taylor <jtaylor@irdg.com>
  81.  
  82.                    Fixed forward reference problem with the
  83.  
  84.                    THTTP_FILTER_CONTEXT structure
  85.  
  86.  
  87.  
  88.   SVG   05/05/96   Translated From C to Delphi 2.0
  89.  
  90.                    by Stephen Genusa <steveg@onramp.net>
  91.  
  92.  
  93.  
  94.  
  95.  
  96. ****************************************************************************)
  97.  
  98.  
  99.  
  100.  
  101.  
  102. Library FiltDemo;
  103.  
  104.  
  105.  
  106. Uses
  107.  
  108.   SysUtils,
  109.  
  110.   Windows;
  111.  
  112.  
  113.  
  114. const
  115.  
  116.  
  117.  
  118.     HTTP_FILTER_MAJOR          = 1; { major version of this spec }
  119.  
  120.     HTTP_FILTER_MINOR          = 0; { minor version of this spec }
  121.  
  122.     SF_MAX_USERNAME            = 257;
  123.  
  124.     SF_MAX_PASSWORD            = 257;
  125.  
  126.     SF_MAX_FILTER_DESC_LEN     = 257;
  127.  
  128.  
  129.  
  130. { SF_STATUS_TYPE }
  131.  
  132.     SF_STATUS_TYPE                     = $8000000;  { base value }
  133.  
  134.     SF_STATUS_REQ_FINISHED             = SF_STATUS_TYPE;
  135.  
  136.     SF_STATUS_REQ_FINISHED_KEEP_CONN   = SF_STATUS_TYPE + 1;
  137.  
  138.     SF_STATUS_REQ_NEXT_NOTIFICATION    = SF_STATUS_TYPE + 2;
  139.  
  140.     SF_STATUS_REQ_HANDLED_NOTIFICATION = SF_STATUS_TYPE + 3;
  141.  
  142.     SF_STATUS_REQ_ERROR                = SF_STATUS_TYPE + 4;
  143.  
  144.     SF_STATUS_REQ_READ_NEXT            = SF_STATUS_TYPE + 5;
  145.  
  146.  
  147.  
  148.     SF_NOTIFY_SECURE_PORT              = $00000001;
  149.  
  150.     SF_NOTIFY_NONSECURE_PORT           = $00000002;
  151.  
  152.     SF_NOTIFY_READ_RAW_DATA            = $00008000;
  153.  
  154.     SF_NOTIFY_PREPROC_HEADERS          = $00004000;
  155.  
  156.     SF_NOTIFY_AUTHENTICATION           = $00002000;
  157.  
  158.     SF_NOTIFY_URL_MAP                  = $00001000;
  159.  
  160.     SF_NOTIFY_SEND_RAW_DATA            = $00000400;
  161.  
  162.     SF_NOTIFY_LOG                      = $00000200;
  163.  
  164.     SF_NOTIFY_END_OF_NET_SESSION       = $00000100;
  165.  
  166.  
  167.  
  168.     SF_NOTIFY_ORDER_HIGH               = $00080000;
  169.  
  170.     SF_NOTIFY_ORDER_MEDIUM             = $00040000;
  171.  
  172.     SF_NOTIFY_ORDER_LOW                = $00020000;
  173.  
  174.     SF_NOTIFY_ORDER_DEFAULT            = SF_NOTIFY_ORDER_LOW;
  175.  
  176.     SF_NOTIFY_ORDER_MASK               = (SF_NOTIFY_ORDER_HIGH or SF_NOTIFY_ORDER_MEDIUM or SF_NOTIFY_ORDER_LOW);
  177.  
  178.  
  179.  
  180. type
  181.  
  182.  
  183.     PVOID = Pointer;
  184.  
  185.     LPVOID = Pointer;
  186.  
  187.     PCardinal = ^Cardinal;
  188.  
  189.  
  190.  
  191.     SF_REQ_TYPE = (SF_REQ_SEND_RESPONSE_HEADER, SF_REQ_ADD_HEADERS_ON_DENIAL,
  192.  
  193.                    SF_REQ_SET_NEXT_READ_SIZE, SF_REQ_SET_PROXY_INFO);
  194.  
  195.  
  196.  
  197.     Type
  198.  
  199.       TFuncPlaceHolder = POINTER;
  200.  
  201.  
  202.  
  203.     THTTP_FILTER_CONTEXT = record
  204.  
  205.       cbSize             : DWORD;
  206.  
  207.       Revision           : DWORD;
  208.  
  209.       ServerContext      : PVOID;
  210.  
  211.       ulReserved         : DWORD;
  212.  
  213.       fIsSecurePort      : BOOL;
  214.  
  215.       pFilterContext     : PVOID;
  216.  
  217.       GetServerVariable  : TFuncPlaceHolder; {TGetServerVariable;}
  218.  
  219.       AddResponseHeaders : TFuncPlaceHolder; {TAddResponseHeaders;}
  220.  
  221.       WriteClient        : TFuncPlaceHolder; {TWriteClient;}
  222.  
  223.       AllocMen           : TFuncPlaceHolder; {TAllocMem;}
  224.  
  225.       ServerSupportFunc  : TFuncPlaceHolder; {TServerSupportFunc;}
  226.  
  227.     end;
  228.  
  229.     HTTP_FILTER_CONTEXT = THTTP_FILTER_CONTEXT;
  230.  
  231.     PHTTP_FILTER_CONTEXT = ^HTTP_FILTER_CONTEXT;
  232.  
  233.  
  234.  
  235.  
  236.  
  237.     TGetServerVariable  = Function(var pfc          : THTTP_FILTER_CONTEXT;
  238.  
  239.                                        VariableName : PChar;
  240.  
  241.                                        Buffer       : PChar;
  242.  
  243.                                        var BuffSize : DWORD) : BOOL;
  244.  
  245.                                        StdCall;
  246.  
  247.  
  248.  
  249.     TAddResponseHeaders = Function(var pfc          : THTTP_FILTER_CONTEXT;
  250.  
  251.                                        Headers      : PChar;
  252.  
  253.                                        Reserved     : DWORD) : BOOL;
  254.  
  255.                                        StdCall;
  256.  
  257.  
  258.  
  259.     TWriteClient        = Function(var pfc          : THTTP_FILTER_CONTEXT;
  260.  
  261.                                        Buffer       : LPVOID;
  262.  
  263.                                        dwBytes      : LPDWORD;
  264.  
  265.                                        Reserved     : DWORD) : BOOL;
  266.  
  267.                                        StdCall;
  268.  
  269.  
  270.  
  271.     TAllocMem           = Procedure(var pfc         : THTTP_FILTER_CONTEXT;
  272.  
  273.                                         cbSize      : DWORD;
  274.  
  275.                                         dwReserved  : DWORD);
  276.  
  277.  
  278.  
  279.     TServerSupportFunc = Function(var  pfc          : THTTP_FILTER_CONTEXT;
  280.  
  281.                                        sfReq        : SF_REQ_TYPE;
  282.  
  283.                                        pData        : PVOID;
  284.  
  285.                                        ul1          : DWORD;
  286.  
  287.                                        ul2          : DWORD) : BOOL;
  288.  
  289.                                        StdCall;
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.     THTTP_FILTER_RAW_DATA = record
  298.  
  299.       pvInData   : PVOID;
  300.  
  301.       cbInData   : DWORD;
  302.  
  303.       cbInBuffer : DWORD;
  304.  
  305.       dwReserved : DWORD;
  306.  
  307.     end;
  308.  
  309.     HTTP_FILTER_RAW_DATA  = THTTP_FILTER_RAW_DATA;
  310.  
  311.     PHTTP_FILTER_RAW_DATA = ^HTTP_FILTER_RAW_DATA;
  312.  
  313.  
  314.  
  315.     TGetHeader = Function(var pfc       : THTTP_FILTER_CONTEXT;
  316.  
  317.                               lpszName  : PChar;
  318.  
  319.                               lpvBuffer : LPVOID;
  320.  
  321.                               lpdwSize  : LPDWORD) : BOOL; StdCall;
  322.  
  323.  
  324.  
  325.     TSetHeader = Function(var pfc : THTTP_FILTER_CONTEXT;
  326.  
  327.                               lpszName  : PChar;
  328.  
  329.                               lpszValue : PChar) : BOOL; StdCall;
  330.  
  331.  
  332.  
  333.     TAddHeader = Function(var pfc : THTTP_FILTER_CONTEXT;
  334.  
  335.                               lpszName  : PChar;
  336.  
  337.                               lpszValue : PChar) : BOOL; StdCall;
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.     THTTP_FILTER_PREPROC_HEADERS = record
  348.  
  349.       GetHeader  : TGetHeader;
  350.  
  351.       SetHeader  : TSetHeader;
  352.  
  353.       AddHeader  : TAddHeader;
  354.  
  355.       dwReserved : DWORD;
  356.  
  357.     end;
  358.  
  359.     HTTP_FILTER_PREPROC_HEADERS  = THTTP_FILTER_PREPROC_HEADERS;
  360.  
  361.     PHTTP_FILTER_PREPROC_HEADERS = ^HTTP_FILTER_PREPROC_HEADERS;
  362.  
  363.  
  364.  
  365.  
  366.  
  367.     THTTP_FILTER_AUTHENT = record
  368.  
  369.       pszUser        : PChar;
  370.  
  371.       cbUserBuff     : DWORD;
  372.  
  373.       pszPassword    : PChar;
  374.  
  375.       cbPasswordBuff : DWORD;
  376.  
  377.     end;
  378.  
  379.     HTTP_FILTER_AUTHENT  = THTTP_FILTER_AUTHENT;
  380.  
  381.     PHTTP_FILTER_AUTHENT = ^HTTP_FILTER_AUTHENT;
  382.  
  383.  
  384.  
  385.  
  386.  
  387.     THTTP_FILTER_URL_MAP = record
  388.  
  389.       pszURL : PChar;
  390.  
  391.       pszPhysicalPath : PChar;
  392.  
  393.       cbPathBuff : DWORD;
  394.  
  395.     end;
  396.  
  397.     HTTP_FILTER_URL_MAP  = THTTP_FILTER_URL_MAP;
  398.  
  399.     PHTTP_FILTER_URL_MAP = ^HTTP_FILTER_URL_MAP;
  400.  
  401.  
  402.  
  403.  
  404.  
  405.     THTTP_FILTER_LOG = record
  406.  
  407.       pszClientHostName : PChar;
  408.  
  409.       pszClientUserName : PChar;
  410.  
  411.       pszServerName     : PChar;
  412.  
  413.       pszOperation      : PChar;
  414.  
  415.       pszTarget         : PChar;
  416.  
  417.       pszParameters     : PChar;
  418.  
  419.       dwHttpStatus      : DWORD;
  420.  
  421.       dwWin32Status     : DWORD;
  422.  
  423.     end;
  424.  
  425.     HTTP_FILTER_LOG  = THTTP_FILTER_LOG;
  426.  
  427.     PHTTP_FILTER_LOG = ^HTTP_FILTER_LOG;
  428.  
  429.  
  430.  
  431.  
  432.  
  433.     THTTP_FILTER_VERSION = record
  434.  
  435.       dwServerFilterVersion : DWORD;
  436.  
  437.       dwFilterVersion       : DWORD;
  438.  
  439.       lpszFilterDesc        : array [0..(SF_MAX_FILTER_DESC_LEN-1)] of Char;
  440.  
  441.       dwFlags               : DWORD;
  442.  
  443.     end;
  444.  
  445.     HTTP_FILTER_VERSION = THTTP_FILTER_VERSION;
  446.  
  447.     PHTTP_FILTER_VERSION = ^HTTP_FILTER_VERSION;
  448.  
  449.     TFilter=class
  450.      public
  451.       procedure AssignContext(var thisFC: HTTP_FILTER_CONTEXT);
  452.       function  GetServerVar(varName: String): String;
  453.      private
  454.       pFC: PHTTP_FILTER_CONTEXT;
  455.     end;
  456.  
  457.  
  458.  
  459. procedure TFilter.AssignContext(var thisFC: HTTP_FILTER_CONTEXT);
  460. begin
  461.   pFC:=@thisFC;
  462. end;
  463.  
  464. function  TFilter.GetServerVar(varName: String): String;
  465. var
  466.   ss: ShortString;
  467.   buf: array[0..255] of char absolute ss;
  468.   len: Integer;
  469.   FNGetServerVariable: TGetServerVariable;
  470. begin
  471.   len:=255;
  472.   @FNGetServerVariable:=pFC^.GetServerVariable;
  473.   if FNGetServerVariable(pFC^, PChar(varName), Pointer(@buf[1]), len ) then
  474.   begin
  475.     ss[0]:=Char(len);
  476.     result:=ss;
  477.   end
  478.   else
  479.     Result:='<UNKNOWN>';
  480. end;
  481.  
  482. function ExpandToken(token, expandedString: String; var buffer: String; var bufferSize: Integer): Integer;
  483. var
  484.   i: Integer;
  485.   newString: String;
  486.   sizeDelta: Integer;
  487. begin
  488.    sizeDelta:=0;
  489.  
  490.    // Keep scanning through the buffer as long
  491.    // as we keep finding occurances of the token
  492.    repeat
  493.      newString:='';
  494.  
  495.      i:=Pos('%'+token+'%', buffer);
  496.      if i<>0 then
  497.      begin
  498.        // We found the token
  499.        newString:=expandedString;
  500.        buffer:=Copy(buffer, 1, i-1)+newString+Copy(buffer, i+Length(token)+2, bufferSize-i);
  501.  
  502.        // Adjust the buffer size
  503.        bufferSize:=bufferSize+Length(expandedString)-Length(token)-2;
  504.      end
  505.    until newString='';
  506.    result:=sizeDelta;
  507. end;
  508.  
  509. procedure ProcessTokens(var buffer: String; var bufferSize: Integer; filter: TFilter);
  510. begin
  511.   ExpandToken('TIME',            DateTimeToStr(Now),                      buffer, bufferSize );
  512.   ExpandToken('REMOTE_ADDR',     filter.GetServerVar('REMOTE_ADDR'),      buffer, bufferSize );
  513.   ExpandToken('REMOTE_USER',     filter.GetServerVar('REMOTE_USER'),      buffer, bufferSize );
  514.   ExpandToken('SERVER_NAME',     filter.GetServerVar('SERVER_NAME'),      buffer, bufferSize );
  515.   ExpandToken('SERVER_SOFTWARE', filter.GetServerVar('SERVER_SOFTWARE'),  buffer, bufferSize );
  516. end;
  517.  
  518. Function GetFilterVersion(var pVer : HTTP_FILTER_VERSION) : BOOL; export; stdcall;
  519.  
  520. begin
  521.   pVer.dwFilterVersion := MAKELONG(0, 1);
  522.   StrPCopy(pVer.lpszFilterDesc, 'Filter Demo version 0.94');
  523.   pVer.dwFlags := (SF_NOTIFY_URL_MAP OR SF_NOTIFY_SEND_RAW_DATA);
  524.   result := True;
  525. end;
  526.  
  527.  
  528.  
  529. Function HttpFilterProc(var pfc : HTTP_FILTER_CONTEXT; NotificationType : DWORD; pvNotification : LPVOID) : DWORD; export; stdcall;
  530. var
  531.   filter: TFilter;
  532.  
  533.    function OnURLMap : DWORD;
  534.    var
  535.      mapStruct: HTTP_FILTER_URL_MAP;
  536.    begin
  537.      result := SF_STATUS_REQ_NEXT_NOTIFICATION;
  538.  
  539.      mapStruct:=HTTP_FILTER_URL_MAP(pvNotification^);
  540.      //PChar(mapStruct.pszPhysicalPath)[mapStruct.cbPathBuff-1]:=#0;
  541.  
  542.      if (Pos('.HTM', String(mapStruct.pszPhysicalPath))<>0 ) OR (Pos('.htm', String(mapStruct.pszPhysicalPath))<>0 ) then
  543.        pfc.pFilterContext:=PVOID(1)
  544.      else
  545.        pfc.pFilterContext:=PVOID(0);
  546.  
  547.  
  548.    end;
  549.  
  550.    // OnSendRawData
  551.    function OnSendRawData : DWORD;
  552.    var
  553.      rawStruct : PHTTP_FILTER_RAW_DATA;
  554.      s : String;
  555.    begin
  556.      result := SF_STATUS_REQ_NEXT_NOTIFICATION;
  557.  
  558.      if pfc.pFilterContext=nil then
  559.        Exit;
  560.  
  561.      // Cast the pointer. Note we keep it a pointer here
  562.      // locally so that we can return any mods made to the
  563.      // struct (such as length)
  564.      rawStruct := PHTTP_FILTER_RAW_DATA(pvNotification);
  565.  
  566.      PChar(rawStruct.pvInData)[rawStruct.cbInBuffer-1]:=#0;
  567.  
  568.      SetLength(s, 16384);
  569.      StrCopy(PChar(s), rawStruct.pvInData);
  570.  
  571.      // Process the tokens and also make the required
  572.      // adjustments to size
  573.      ProcessTokens(s, rawStruct.cbInData, filter);
  574.  
  575.  
  576.      StrCopy(rawStruct.pvInData, PChar(s));
  577.    end;
  578.  
  579.  
  580.  
  581.  
  582.  
  583. begin
  584.   result:=SF_STATUS_REQ_NEXT_NOTIFICATION;
  585.   //Exit;
  586.  
  587.   try
  588.     filter:=TFilter.Create;
  589.  
  590.     filter.AssignContext(pfc);
  591.  
  592.     Case NotificationType of
  593.       SF_NOTIFY_URL_MAP:
  594.       begin
  595.         result:=OnURLMap;
  596.       end;
  597.       SF_NOTIFY_SEND_RAW_DATA:
  598.       begin
  599.         result := OnSendRawData;
  600.       end;
  601.     end;
  602.     filter.Free;
  603.   except
  604.     ;
  605.   end;
  606. end;
  607.  
  608.  
  609.  
  610.  
  611.  
  612. exports
  613.  
  614.   HttpFilterProc,
  615.  
  616.   GetFilterVersion;
  617.  
  618.  
  619.  
  620.  
  621.  
  622. end.
  623.  
  624.  
  625.  
  626.